package com.ruoyi.controller;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.constants.Constant;
import com.ruoyi.dto.RiverGridPoint;
import com.ruoyi.dto.RiverGridVelocity;
import com.ruoyi.dto.RiverHydraulicInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 河道一维水力学模型计算类
 */
@Api(tags = "风险评估")
@RequestMapping("/riverHydraulicModel")
@RestController
public class RiverHydraulicModelController {


    // 监测点信息
    private MonitoringPoint monitoringPoint;

    // 网格数据
    private List<RiverGridPoint> gridPoints;


    @ApiOperation("河道一维水力学模型")
    @PostMapping("/oneDimensional")
    public AjaxResult riverHydraulicModel(@RequestBody RiverHydraulicInfo riverHydraulicInfo) {
        AjaxResult ajaxResult = new AjaxResult();
        DecimalFormat df = new DecimalFormat("#.00");
        Map map = new HashMap();

        List<RiverGridVelocity> riverGridVelocityList = new ArrayList<>();

        map.put("number",riverHydraulicInfo.getNumber());
        map.put("input",riverHydraulicInfo);

        for (RiverGridPoint riverGridPoint : riverHydraulicInfo.getRiverGridPointList()) {
            Double gridLength = Constant.GRID_LENGTH;
            RiverGridVelocity riverGridVelocity = new RiverGridVelocity();
            if(null != riverGridPoint.getGridLength())
            {
                gridLength = riverGridPoint.getGridLength();
            }

            BeanUtils.copyProperties(riverGridPoint,riverGridVelocity);
            riverGridVelocity.setV(Double.valueOf(df.format(calculateCompleteVelocity(riverGridPoint.getH1(),riverGridPoint.getH2(),gridLength,
                    riverGridPoint.getH(),riverGridPoint.getW()).velocity)));

            riverGridVelocityList.add(riverGridVelocity);
        }

        map.put("result" , riverGridVelocityList);

        return ajaxResult.success(map);
    }

        /**
         * 计算河道坡度
         * @param startElevation 起点高程
         * @param endElevation 终点高程
         * @param distance 距离（默认为10米）
         * @return 坡度 S
         */
    public double calculateSlope(double startElevation, double endElevation, double distance) {
        return (startElevation - endElevation) / distance;
    }

    /**
     * 计算水力半径
     * @param waterLevel 水位 h1 (米)
     * @param riverWidth 河宽 w (米)
     * @return 水力半径 R
     */
    public double calculateHydraulicRadius(double waterLevel, double riverWidth) {
        double crossSectionArea = waterLevel * riverWidth; // 过水断面面积
        double wettedPerimeter = 2 * waterLevel + riverWidth; // 湿周
        return crossSectionArea / wettedPerimeter;
    }

    /**
     * 计算流速
     * @param hydraulicRadius 水力半径
     * @param slope 坡度
     * @param lambda 阻力系数
     * @return 流速 v_n (m/s)
     */
    public double calculateVelocity(double hydraulicRadius, double slope, double lambda) {
        double coefficient = Math.sqrt((8 * Constant.GRAVITY) / lambda);
        return coefficient * Math.sqrt(hydraulicRadius * Math.abs(slope));
    }

    /**
     * 完整的流速计算流程
     * @param startElevation 网格起点高程
     * @param endElevation 网格终点高程
     * @param gridLength 网格长度
     * @param waterLevel 监测点水位
     * @param riverWidth 监测点河宽
     * @return 流速计算结果
     */
    public VelocityResult calculateCompleteVelocity(double startElevation, double endElevation, double gridLength,
                                                    double waterLevel, double riverWidth) {
        double slope = calculateSlope(startElevation, endElevation, gridLength);
        double hydraulicRadius = calculateHydraulicRadius(waterLevel, riverWidth);
        double velocity = calculateVelocity(hydraulicRadius, slope, Constant.DEFAULT_LAMBDA);

        return new VelocityResult(slope, hydraulicRadius, velocity);
    }




    // 内部类：监测点
    public static class MonitoringPoint {
        private double x;
        private double y;
        private double z;
        private double waterLevel;
        private double riverWidth;

        public MonitoringPoint(double x, double y, double z, double waterLevel, double riverWidth) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.waterLevel = waterLevel;
            this.riverWidth = riverWidth;
        }

        // getters and setters
        public double getX() { return x; }
        public double getY() { return y; }
        public double getZ() { return z; }
        public double getWaterLevel() { return waterLevel; }
        public double getRiverWidth() { return riverWidth; }
    }

    // 内部类：流速计算结果
    public static class VelocityResult {
        private double slope;
        private double hydraulicRadius;
        private double velocity;

        public VelocityResult(double slope, double hydraulicRadius, double velocity) {
            this.slope = slope;
            this.hydraulicRadius = hydraulicRadius;
            this.velocity = velocity;
        }

        // getters
        public double getSlope() { return slope; }
        public double getHydraulicRadius() { return hydraulicRadius; }
        public double getVelocity() { return velocity; }

        @Override
        public String toString() {
            return String.format("坡度: %.4f, 水力半径: %.3f m, 流速: %.3f m/s",
                    slope, hydraulicRadius, velocity);
        }
    }

    // 使用示例
    public static void main(String[] args) {
        RiverHydraulicModelController model = new RiverHydraulicModelController();


    }
}
